perm filename MACRO.MSS[WHT,LSP] blob
sn#754066 filedate 1984-05-12 generic text, type T, neo UTF8
@Part[Macro, Root = "CLM.MSS"]
@Comment{Chapter of Common Lisp Manual. Copyright 1984 Guy L. Steele Jr.⎇
@MyChapter[Macros]
@Label[MACROS]
The @cLisp macro facility allows the user to define arbitrary
functions that convert certain @xlisp forms into different forms before
evaluating or compiling them. This is done at the expression level,
not at the character-string level as in most other languages. Macros
are important in the writing of good code: they make it possible to
write code that is clear and elegant at the user level, but that is
converted to a more complex or more efficient internal form for
execution.
When @Funref[eval] is given a list whose @i[car] is a symbol, it looks
for local definitions of that symbol (by @Specref[flet], @Specref[labels],
and @Specref[macrolet]); if that fails, it looks for a global definition.
If the definition is a macro definition, then the original
list is said to be a @i[macro call]. Associated with the definition
will be a function of two arguments, called the @i[expansion function].
This function is called with the entire macro call as its first argument
(the second argument is a lexical environment);
it must return some new @xlisp form, called the @i[expansion] of the
macro call. (Actually, a more general mechanism is involved;
see @Funref[macroexpand].)
This expansion is then evaluated in place of the original
form.
When a function is being compiled, any macros it contains are expanded
at compilation time. This means that a macro definition must be seen by the
compiler before the first use of the macro.
More generally, an implementation of @clisp has great latitude in deciding
exactly when to expand macro calls within a program. For example,
it is acceptable for the @macref[defun] special form to expand all macro
calls within its body at the time the @f[defun] form is executed
and record the fully expanded body as the body of the function
being defined.
(An implementation might even choose always to compile functions defined
by @f[defun], even when operating in an ``interpretive'' mode!)
Macros should be written in such a way as to depend as little as possible
on the execution environment to produce a correct expansion. To ensure
consistent behavior, it is best to ensure that all macro definitions are
available, whether to the interpreter or compiler, before any code
containing calls to those macros is introduced.
In @clisp, macros are not functions.
In particular, macros cannot be used as
functional arguments to such functions as @Funref[apply], @Funref[funcall],
or @Funref[map]; in such situations, the list representing the ``original macro
call'' does not exist, and cannot exist, because in some sense the arguments
have already been evaluated.
@Section[Macro Definition]
The function @f[macro-function] determines whether a given symbol
is the name of a macro. The @f[defmacro] construct provides
a convenient way to define new macros.
@Defun[Fun {macro-function⎇, Args {@i[symbol]⎇]
The argument must be a symbol. If the symbol has a global function definition
that is a macro definition, then the expansion function
(a function of two arguments, the macro-call form and an environment)
is returned.
If the symbol has no global function definition, or has a definition
as an ordinary function or as a special form but not as a macro, then
@false is returned. The function @Funref[macroexpand]
is the best way to invoke the expansion function.
It is possible for @i[both] @f[macro-function] and @Funref[special-form-p]
to be true of a symbol. This is possible because an implementation is
permitted to implement any macro also as a special form for speed.
On the other hand, the macro definition must be available
for use by programs that understand only the standard special forms
listed in Table @Ref[Special-Form-Table].
@f[macro-function] cannot be used to determine whether a symbol names
a locally defined macro established by @Specref[macrolet];
@f[macro-function] can
examine only global definitions.
@Macref[setf] may be used with @f[macro-function] to install
a macro as a symbol's global function definition:
@lisp
(setf (macro-function @i[symbol]) @i[fn])
@endlisp
The value installed must be a function that accepts one argument,
the entire macro call, and computes the expansion for that call.
Performing this operation causes the symbol to have @i[only] that
macro definition as its global function definition; any previous
definition, whether as a macro or as a function, is lost.
It is an error to attempt to redefine the name of a special
form (see Table @ref[SPECIAL-FORM-TABLE]).
@Enddefun
@Defmac[Fun {defmacro⎇, Args {@i[name] @i[lambda-list] @Mstar<@i[declaration] @mor @i[doc-string]> @Mstar<@i[form]>⎇]
@f[defmacro] is a macro-defining macro that
arranges to decompose the macro-call form in an elegant and useful way.
@f[defmacro] has essentially the same syntax as @Macref[defun]: @i[name] is the
symbol whose macro definition we are creating, @i[lambda-list] is similar in
form to a lambda-list, and
the @i[forms] constitute the body of the expander function.
The @f[defmacro] construct arranges to install this expander function,
as the global macro definition of @i[name]. The expander function
is effectively defined in the @i[global] environment;
lexically scoped entities established
outside the @f[defmacro] form that would ordinarily be lexically apparent
are not visible within the body of the expansion function.
The @i[name] is returned
as the value of the @f[defmacro] form.
If we view the
macro call as a list containing a function name and some argument forms,
in effect the expander function and the list of (unevaluated) argument
forms is given to @Funref[apply].
The parameter specifiers are processed as for any lambda-expression,
using the macro-call argument forms as the arguments.
Then the body forms are evaluated
as an implicit @f[progn], and the value of the last form
is returned as the expansion of the macro call.
If the optional documentation string @i[doc-string] is present (if not
followed by a declaration, it may be
present only if at least one @i[form] is also specified, as it is
otherwise taken to be a @i[form]), then it is attached to the @i[name]
as a documentation string of type @f[function]; see @Funref[documentation].
Like the lambda-list in a @f[defun], a @f[defmacro] @i[lambda-list] may contain
the lambda-list keywords @optional, @rest, @key, @allowotherkeys, and @aux.
For @optional and @key parameters, initialization forms and ``supplied-p''
parameters may be specified, just as for @f[defun].
Three additional markers
are allowed in @f[defmacro] variable lists only:
@Begin[description]
@body@\This is identical in function to @rest, but it informs certain
output-formatting and editing functions that the remainder of the form is
treated as a body, and should be indented accordingly.
(Only one of @body or @rest may be used.)
@whole@\This is followed by a single variable that is bound to the
entire macro-call form; this is the value that the macro definition function
receives as its single argument.
@whole and the following variable should appear first in the lambda-list,
before any other parameter or lambda-list keyword.
@f[&environment]@\This is followed by a single variable that is bound
to an environment representing the lexical environment in which the
macro call is to be interpreted. This environment may not be the
complete lexical environment; it should be used only with
the function @Funref[macroexpand] for the sake of any local
macro definitions that the @specref[macrolet] construct may have
established within that lexical environment. This is useful primarily
in the rare cases where a macro definition must explicitly expand any macros
in a subform of the macro call before computing its own expansion.
@End[Description]
See @Conref[lambda-list-keywords].
@f[defmacro], unlike any other @clisp construct that has a lambda-list
as part of its syntax, provides an additional facility known as
@def[destructuring]. Anywhere in the lambda-list where a parameter
name may appear, and where ordinary lambda-list syntax (as described
in section @ref[LAMBDA-EXPRESSIONS-SECTION]) does not
otherwise allow a list, a lambda-list may appear in place
of the parameter name. When this is done, then the argument form
that would match the parameter is treated as a (possibly dotted) list,
to be used as an argument forms list for satisfying the
parameters in the embedded lambda-list.
As an example, one could write the macro definition
for @Macref[dolist] in this manner:
@lisp
(defmacro dolist ((var listform @optional resultform)
&rest body)
...)
@endlisp
More examples of embedded lambda-lists in @f[defmacro] are shown below.
Another destructuring rule is that @f[defmacro] allows any lambda-list
(whether top-level or embedded) to be dotted, ending
in a parameter name. This situation is treated exactly as if the
parameter name that ends the list had appeared preceded by @rest.
For example, the definition skeleton for @f[dolist] shown above could
instead have been written
@lisp
(defmacro dolist ((var listform &optional resultform)
. body)
...)
@endlisp
If the compiler encounters a @f[defmacro],
the new macro is added to the compilation
environment, and a compiled form of the expansion function is also added
to the output file so that the new macro will be operative at runtime.
If this is not the desired effect, the @f[defmacro] form can be wrapped
in an @Specref[eval-when] construct.
It is permissible to use @f[defmacro] to redefine a macro
(for example, to install
a corrected version of an incorrect definition!), or to redefine
a function as a macro.
It is an error to attempt to redefine the name of a special
form (see Table @ref[SPECIAL-FORM-TABLE]) as a macro.
See also @Specref[macrolet], which establishes macro
definitions over a restricted lexical scope.
@Enddefmac
Suppose, for the sake of example, that it were desirable
to implement a conditional construct analogous to the
@fortran arithmetic IF statement. (This of course requires a certain
stretching of the imagination and suspension of disbelief.)
The construct should accept four forms: a @i[test-value],
a @i[neg-form], a @i[zero-form], and a @i[pos-form].
One of the last three forms is chosen to be executed according
to whether the value of the @i[test-form] is positive, negative,
or zero.
Using @f[defmacro], a definition for such a construct
might look like this:
@lisp
(defmacro arithmetic-if (test neg-form zero-form pos-form)
(let ((var (gensym)))
@bq@;(let ((,var ,test))
(cond ((< ,var 0) ,neg-form)
((= ,var 0) ,zero-form)
(t ,pos-form)))))
@endlisp
Note the use of the backquote facility in this definition.
See section @ref[MACRO-CHARACTERS-SECTION].
Also note the use of @Funref[gensym] to generate a new variable name.
This is necessary to avoid conflict with any variables that might
be referred to in @i[neg-form], @i[zero-form], or @i[pos-form].
If the form is executed by the interpreter, it will cause the
function definition of the symbol @f[arithmetic-if]
to be a macro associated with which is
a two-argument expansion function roughly equivalent to:
@lisp
(lambda (calling-form environment)
(declare (ignore environment))
(let ((var (gensym)))
(list 'let
(list (list 'var (cadr calling-form)))
(list 'cond
(list (list '< var '0) (caddr calling-form))
(list (list '= var '0) (cadddr calling-form))
(list 't (fifth calling-form))))))
@endlisp
The lambda-expression is produced by the @f[defmacro] declaration.
The calls to @f[list] are the (hypothetical) result of the backquote (@f[@bq])
macro character and its associated commas.
The precise macro expansion function may depend on the implementation,
for example providing some degree of explicit error checking on the number
of argument forms in the macro call.
Now, if @f[eval] encounters
@lisp
(arithmetic-if (- x 4.0)
(- x)
(error "Strange zero")
x)
@endlisp
this will be expanded into something like
@lisp
(let ((g407 (- x 4.0)))
(cond ((< g407 0) (- x))
((= g407 0) (error "Strange zero"))
(t x)))
@endlisp
and @f[eval] tries again on this new form.
(It should be clear now that the backquote facility
is very useful in writing macros, since the form to be returned is
normally a complex list structure, typically consisting of a
mostly constant template with a few evaluated forms here and there.
The backquote template provides a ``picture'' of the resulting
code, with places to be filled in indicated by preceding commas.)
To expand on this example, stretching credibility to its limit,
we might allow the @i[pos-form]
and @i[zero-form] to be omitted, allowing their values to default to @nil,
in much the same way that the @i[else] form of a @clisp @Specref[if] construct
may be omitted:
@lisp
(defmacro arithmetic-if (test neg-form @optional zero-form pos-form)
(let ((var (gensym)))
@bq@;(let ((,var ,test))
(cond ((< ,var 0) ,neg-form)
((= ,var 0) ,zero-form)
(t ,pos-form)))))
@endlisp
Then one could write
@lisp
(arithmetic-if (- x 4.0) (print x))
@endlisp
which would be expanded into something like
@lisp
(let ((g408 (- x 4.0)))
(cond ((< g408 0) (print x))
((= g408 0) nil)
(t nil)))
@endlisp
The resulting code is correct but rather silly-looking.
One might rewrite the macro definition to produce better code
when @i[pos-form] and possibly @i[zero-form] are omitted,
or one might simply rely on the @clisp implementation to provide
a compiler smart enough to improve the code itself.
Destructuring is a very powerful facility that allows
the @f[defmacro] lambda-list to express the structure of
a complicated macro-call syntax. If no lambda-list keywords
appear, then the @f[defmacro] lambda-list is simply a list,
nested to some extent, containing parameter names at the leaves.
The macro-call form must have the same list structure.
For example, consider this macro definition:
@lisp
(defmacro halibut ((mouth eye1 eye2)
((fin1 length1) (fin2 length2))
tail)
@endlisp
Now consider this macro call:
@lisp
(halibut (m (car eyes) (cdr eyes))
((f1 (count-scales f1)) (f2 (count-scales f2)))
my-favorite-tail)
@endlisp
This would cause the expansion function to receive the following
values for its parameters:
@lisp
@tabset[+10]
@ux[@r[Parameter]]@\@ux[@r[Value]]
mouth@\m
eye1@\(car eyes)
eye2@\(cdr eyes)
fin1@\f1
length1@\(count-scales f1)
fin2@\f2
length2@\(count-scales f2)
tail@\my-favorite-tail
@endlisp
The following macro call would be in error because there would be no
argument form to match the parameter @f[length1]:
@lisp
(halibut (m (car eyes) (cdr eyes))
((f1) (f2 (count-scales f2)))
my-favorite-tail)
@endlisp
The following macro call would be in error because a symbol appears
in the call where the structure of the lambda-list requires a list:
@lisp
(halibut my-favorite-head
((f1 (count-scales f1)) (f2 (count-scales f2)))
my-favorite-tail)
@endlisp
The fact that the value of the variable @f[my-favorite-head]
might happen to be a list is irrelevant here. It is the macro call
itself whose structure must match that of the @f[defmacro] lambda-list.
The use of lambda-list keywords adds even greater flexibility.
For example, suppose it is convenient within the expansion
function for @f[halibut] to be able to refer to the list
whose components are called @f[mouth], @f[eye1], and @f[eye2] as @f[head].
One may write this:
@lisp
(defmacro halibut ((@whole head mouth eye1 eye2)
((fin1 length1) (fin2 length2))
tail)
@endlisp
Now consider the same valid macro call as before:
@lisp
(halibut (m (car eyes) (cdr eyes))
((f1 (count-scales f1)) (f2 (count-scales f2)))
my-favorite-tail)
@endlisp
This would cause the expansion function to receive the same
values for its parameters and also a value for the parameter @f[head]:
@lisp
@tabset[+10]
@ux[@r[Parameter]]@\@ux[@r[Value]]
head@\(m (car eyes) (cdr eyes))
@endlisp
The stipulation, that
an embedded lambda-list is permitted only
where ordinary lambda-list syntax would permit a parameter name
but not a list, is made to prevent ambiguity. For example,
one may not write
@lisp
(defmacro loser (x @optional (a b @rest c) @rest z)
...)
@endlisp
because ordinary lambda-list syntax does permit a list following @optional;
the list @f[(a b @rest c)] would be interpreted as describing an
optional parameter named @f[a] whose default value is that of the
form @f[b], with a supplied-p parameter named @rest (not legal),
and an extraneous symbol @f[c] in the list (also not legal). An almost
correct way to express this is
@lisp
(defmacro loser (x @optional ((a b @rest c)) @rest z)
...)
@endlisp
The extra set of parentheses removes the ambiguity. However, the
definition is now incorrect because a macro call such as @f[(loser (car pool))]
would not provide any argument form for the lambda-list @f[(a b @rest c)],
and so the default value against which to match the lambda-list would be
@nil because no explicit default value was specified. This is in error
because @nil is an empty list; it does not have forms to satisfy the
parameters @f[a] and @f[b]. The fully correct definition would be either
@lisp
(defmacro loser (x @optional ((a b @rest c) '(nil nil)) @rest z)
...)
@endlisp
or
@lisp
(defmacro loser (x @optional ((@optional a b @rest c)) @rest z)
...)
@endlisp
These differ slightly: the first requires that if the macro call
specifies @f[a] explicitly then it must also specify @f[b] explicitly,
whereas the second does not have this requirement. For example,
@lisp
(loser (car pool) ((+ x 1)))
@endlisp
would be a valid call for the second definition but not for the first.
@Section[Macro Expansion]
The @f[macroexpand] function is the conventional means for
expanding a macro call. A hook is provided for a user function
to gain control during the expansion process.
@Defun[Fun {macroexpand⎇, Args {@i[form] @optional @i[env]⎇]
@Defun1[Fun {macroexpand-1⎇, Args {@i[form] @optional @i[env]⎇]
If @i[form] is a macro call, then @f[macroexpand-1] will expand the macro
call @i[once] and return two values: the expansion and @f[t].
If @i[form] is not a macro call, then the two values @i[form] and @nil are
returned.
A @i[form] is considered to be a macro call only if it is a cons whose
@i[car] is a symbol that names a macro. The environment @i[env] is similar
to that used within the evaluator (see @Funref[evalhook]);
it defaults to a null environment.
Any local macro definitions established within @i[env] by
@Specref[macrolet] will be considered. If only @i[form] is given as an
argument, then the environment is effectively null,
and only global macro definitions
(as established by @Macref[defmacro]) will be considered.
Macro expansion is carried out as follows. Once @f[macroexpand-1] has
determined that a symbol names a macro, it obtains the expansion
function for that macro. The value of the variable
@Varref[macroexpand-hook] is then called as a function of three arguments:
the expansion function, the @i[form], and the environment @i[env].
The value returned from
this call is taken to be the expansion of the macro call.
The initial value of @var[macroexpand-hook] is @Funref[funcall],
and the net effect is to invoke the expansion function, giving
it @i[form] and @i[env] as its two arguments. (The purpose of
@var[macroexpand-hook] is to facilitate various techniques
for improving interpretation speed by caching macro expansions.)
The evaluator expands macro calls as if through the use of @f[macroexpand-1];
the point is that @Funref[eval] also uses @var[macroexpand-hook].
@f[macroexpand] is similar to @f[macroexpand-1],
but repeatedly expands @i[form] until it is no longer a macro call.
(In effect, @f[macroexpand] simply calls @f[macroexpand-1] repeatedly
until the second value returned is @nil.)
A second value of @f[t] or @nil is returned as for @f[macroexpand-1],
indicating whether the original @i[form] was a macro call.
@Enddefun
@Defvar[Var {macroexpand-hook⎇]
The value of @var[macroexpand-hook] is used as the expansion
interface hook by @Funref[macroexpand-1].
@Enddefvar